週刊Automatineマガジン 4.コンディションの更新
概要
UpdateでAutoの更新が行われるが、コンディションの更新もそこで行われる。
ただし、newを使ってAutoを切り替えるときは要注意、みたいな話。
ここでは、「コンディションはどうやって変化するのか」というのを解説する。
Automatineは各TackにTypeとValueという値のペアをセットすることができる。
実行中、「このフレーム内ならこういう状態」というのを表現することができるというわけ。
で、じゃあ次のタイミングの時、Autoの状態はそれぞれどうなってるの?っていう。
・Autoを初期化した時
・AutoをUpdateする前
・AutoをUpdateした後
初期化時
Autoには3つの初期化方法がある。
1.newを使って初期化する
auto = new Auto<I, U>(frame, IValue)
2.Autoクラスのinstance method ChangeToWithoutInheritConditions(Auto<I, U> newAuto)) を使う
auto = auto.ChangeToWithoutInheritConditions(new Auto<I, U>(frame, IValue))
3.Autoクラスのinstance method ChangeTo(Auto<I, U> newAuto)) を使う
auto = auto.ChangeTo(new Auto<I, U>(frame, IValue))
なぜ初期化に3つも方法があるのかというと、「直前のAutoの状態を引き継ぎたい」というケースがあるため。
1, 2の方法は、直前のAutoの状態の引き継ぎを行わず、
3だけは直前のAutoの状態の引き継ぎを行う。
ぶっちゃけると、
・最初のAutoを作り出す時はnew
・それ以降のAutoを変更したり更新したりするときにはChangeToメソッドを使う
というルールで覚えてもらって構わない。理由はこのページで後述する。
で、状態の話なんだけど、
初期化ずみのAutoは、特例として、実行前にもかかわらずConditionを返すことができる。
new、ChangeToWithoutInheritConditionsメソッドを使ってAutoを初期化/更新した場合、
実行前のAutoは、無条件に0フレーム目のConditionを返す。
対として、
ChangeToメソッドを使ってAutoを初期化/更新した場合、
実行前のAutoは、直前のAutoのConditionを返す。
この、メソッドによるautoの更新の特性の違いは、実際に使用する際にかなり顕著に出てくることになる。
具体的には、autoを更新する目的でnewやChangeToWithoutInheritConditionsメソッドを使うと、意図しない挙動を生みやすくなる。
Update前
Update前のAutoは、直前のUpdateで設定されたConditionを返す。
特に「初期化/更新したばかり」のAutoには特例があり、
new、ChangeToWithoutInheritConditionsメソッドを使ってAutoを初期化/更新した場合、
実行前のAutoは、無条件に0フレーム目のConditionを返す。
対として、
ChangeToメソッドを使ってAutoを初期化/更新した場合、
実行前のAutoは、直前のAutoのConditionを返す。
Update後
AutoのUpdateを行うと、そのタイミングに設定された動作を行う。
もし初めてのUpdateなら、ここで初めて、Auto自体にそのフレームでのConditionが付与されることになる。
ここに特例はない。
例えばその回でAutoの実行が完了する場合でも、最後のタイミングでセットされたConditionは正確に発現する。
初期化からUpdateにかけてのConditionを書くとこんな感じ
autoの初期化 or 更新から、Updateの流れを書き出してみると、次のような形になる。
(初期化/更新)
auto = new NewAuto<I, U>(0, IValue)
or
auto = auto.ChangeToWithoutInheritConditions(new NewAuto<I, U>(0, IValue))
or
auto = auto.ChangeTo(new NewAuto<I, U>(0, IValue))
― --- ---
(frame = 0)
// auto.Conditions()は0フレーム時の結果を返す(前のAutoのCondition or 新規Autoのデフォルト
Update(frame, UValue) (0フレームの適応をしてる
// auto.Conditions()は0フレーム時の結果を返す
frame++
― --- ---
(frame = 1)
// auto.Conditions()は0フレーム時の結果を返す
Update(frame, UValue) (1フレームの適応をしてる
// auto.Conditions()は1フレーム時の結果を返す
frame++
― --- ---
(frame = 2)
// auto.Conditions()は1フレーム時の結果を返す
Update(frame, UValue) (2フレームの適応をしてる
// auto.Conditions()は2フレーム時の結果を返す
frame++
…
注目すべきはframe = 0時のところで、
(frame = 0)
// auto.Conditions()は0フレーム時の結果を返す(前のAutoのCondition or 新規Autoのデフォルト
Update(frame, UValue) (0フレームの適応をしてる
…
0フレーム、autoの 初期化 か 更新 が終わってから一度もUpdateしていない状態でどんなConditionを返すのかが、
どの方法でautoの初期化をしたかで異なる。
new、ChangeToWithoutInheritConditionsメソッドを使ってAutoを初期化/更新した場合、
実行前のAutoは、無条件に0フレーム目のConditionを返す。
対として、
ChangeToメソッドを使ってAutoを初期化/更新した場合、
実行前のAutoは、直前のAutoのConditionを返す。
あっこのコピペ3度目だ。
状態だけを見ていくと、違いがわかりやすい。
newかChangeToWithoutInheritConditionsを使った場合
auto = new Auto
auto = auto.ChangeToWithoutInheritConditions(new Auto)
― --- ---
実行前のconditionは新Autoの0フレーム目
Update
実行後のconditionは新Autoの0フレーム目
ChangeToを使った場合
auto = auto.ChangeTo(new Auto)
― --- ---
conditionは旧Autoの最後の状態
Update
実行後のconditionは新Autoの0フレーム目
太字部分の差が出る。
これは特に、autoの更新を行う際、
newやChangeToWithoutInheritConditionsを使うと
「うっかりUpdate前にConditionを取得して連続してないのが帰ってきて困る」みたいな問題を生みやすい。
なので、次のルールを鉄則にしておくといい。
・最初のAutoを作り出す時はnew
・それ以降のAutoを変更したり更新したりするときにはChangeToメソッドを使う
もちろん意図的に前のAutoのconditionを継がずに0フレーム目を出したい、というケース(猟奇的だ)に対応する場合、
単にnewで書くよりは、ChangeToWithoutInheritConditions という長ったらしいメソッドを使うと、より意図を鮮明にできると思うのでオススメ。